<template>
    <div class="header">
        <div class="icon back">
            <router-link to="/chooseLevel">
                <svg style="vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2161">
                    <path d="M128.512 512l336.969143 336.969143-51.712 51.712L0 486.912 413.769143 73.142857l51.712 51.712L151.478857 438.857143H1024v73.142857z" p-id="2162"></path>
                </svg>
            </router-link>
        </div>
        <div class="title">推箱子</div>
        <div class="icon setting">
            <svg style="vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3057">
                <path d="M510.421333 371.306667c-76.736 0-139.178667 62.997333-139.178666 140.416s62.442667 140.437333 139.178666 140.437333 139.178667-62.997333 139.178667-140.437333-62.442667-140.416-139.178667-140.416z m0 238.165333c-52.309333 0-96.512-44.778667-96.512-97.770667s44.202667-97.749333 96.512-97.749333c52.330667 0 96.512 44.757333 96.512 97.749333s-44.181333 97.770667-96.512 97.770667z m322.112-71.573333l-24.874666-15.296c0.384-3.477333 0.64-7.04 0.64-10.88 0-3.733333 0-7.381333-0.170667-11.157334l24.170667-14.890666c40.448-23.658667 54.506667-75.84 31.36-116.266667l-54.698667-96.362667c-20.288-38.08-68.821333-56.170667-115.84-32.32l-25.045333 14.293334a519.530667 519.530667 0 0 0-16.896-10.112v-30.144c0-46.784-37.781333-84.842667-84.181334-84.842667h-109.994666c-46.421333 0-84.181333 38.058667-84.181334 84.842667v29.610666c-5.76 3.093333-11.562667 6.528-17.429333 10.346667l-23.168-13.205333c-15.402667-10.368-32.106667-11.562667-43.328-11.562667-29.824 0-57.216 15.701333-73.557333 42.56l-54.954667 96.789333c-23.210667 40.469333-9.173333 92.672 30.890667 116.096l25.045333 15.424c-0.362667 3.477333-0.64 7.018667-0.64 10.88 0 3.733333 0 7.402667 0.170667 11.178667l-24.192 14.869333c-40.448 23.658667-54.506667 75.861333-31.338667 116.288l54.72 96.362667c20.309333 38.058667 68.992 56.085333 115.84 32.298667l25.024-14.293334c5.568 3.456 11.2 6.848 16.896 10.112v30.122667c0 46.784 37.76 84.864 84.181333 84.864h109.994667c46.421333 0 84.181333-38.058667 84.181333-84.864v-29.610667c5.781333-3.093333 11.562667-6.528 17.429334-10.346666l23.146666 13.184c15.402667 10.368 32.128 11.584 43.349334 11.584 29.824 0 57.216-15.68 73.536-42.538667l55.573333-97.941333c21.12-42.602667 7.466667-92.010667-31.658667-115.072z m-5.952 95.082666l-54.677333 96.298667c-8.32 13.696-21.738667 21.525333-36.778667 21.525333-9.088 0-15.082667-1.322667-20.842666-5.12l-48.085334-27.456-11.114666 8.042667a195.328 195.328 0 0 1-33.984 20.053333l-12.586667 5.653334v56.682666c0 23.274667-18.624 42.197333-41.514667 42.197334h-109.994666c-22.890667 0-41.514667-18.922667-41.514667-42.197334V752.64l-11.712-5.909333c-11.669333-5.888-23.466667-13.333333-35.968-21.226667l-10.837333-6.826667-46.314667 26.474667c-23.530667 11.904-48.170667 3.584-58.24-15.317333l-55.04-96.917334c-11.413333-19.925333-4.16-46.634667 16.234667-58.56l48.768-29.994666-2.88-14.549334c-1.173333-5.888-1.173333-10.752-1.173334-18.090666 0-3.136 0.341333-5.952 0.661334-8.768a120.96 120.96 0 0 0 0.917333-13.44v-11.925334L213.226667 448.853333c-19.989333-11.690667-27.242667-38.378667-15.786667-58.368l54.656-96.298666c8.341333-13.674667 21.738667-21.525333 36.778667-21.525334 9.066667 0 15.104 1.322667 20.842666 5.12l48.064 27.456 11.136-8.021333a192.768 192.768 0 0 1 33.962667-20.053333l12.608-5.653334V214.826667c0-23.253333 18.624-42.176 41.514667-42.176h109.994666c22.890667 0 41.514667 18.922667 41.514667 42.176v56l11.712 5.909333c11.690667 5.888 24.021333 13.696 35.946667 21.226667l10.837333 6.848 46.336-26.496c23.530667-11.946667 48.170667-3.584 58.24 15.317333l55.018667 96.917333c11.413333 19.925333 4.16 46.613333-16.256 58.56l-48.725334 29.994667 2.858667 14.528c1.173333 5.888 1.173333 10.752 1.173333 18.090667 0 3.136-0.362667 5.973333-0.64 8.810666a120.597333 120.597333 0 0 0-0.917333 13.44v11.925334l46.677333 28.736c19.733333 11.52 26.282667 37.077333 15.808 58.346666z" fill="#222222" p-id="3058"></path>
            </svg>
        </div>
    </div>
    <div class="board" :style="boardStyle">
        <div class="row" v-for="(item,x) in boardConfig" :style="{'width' :boardConfig[0].length * 50 + 'px'}" :key="'boardItem_' + x">
            <block :moveStatus="moveStatus" :boardConfig="boardConfig" :x="x" :y="y" :key="'child_' + y" :child="child" v-for="(child,y) in item"></block>
        </div>
        <div class="NPC_board">
            <block class="npc" :class="'ani_' + moveStatus + (keyPerss ? ' keyPerss' : '') + (init ? ' transition' : '')" :style="{
                top : playerLocation[0] * 50 + 'px',
                left : playerLocation[1] * 50 + 'px'
            }" :moveStatus="moveStatus" :boardConfig="boardConfig" :x="playerLocation[0]" :y="playerLocation[1]" :child="5"></block>
        </div>
    </div>

</template>

<script>
import keyBoradEvent from '../keyBorad'
import block from './block'
import { computed, toRefs, reactive, onMounted, onUnmounted, nextTick } from 'vue'
export default {
    props: ['id'],
    name: 'GAME',
    components: {
        block
    },
    setup(props) {
        // 获取列表数据ID
        const { id } = toRefs(props);
        // 按键状态缓存
        var keyPerss = {
            delay: false,
            timer: { up: null, down: null, left: null, right: null },
            lastAnimationTimer: 0,
            clear: null,
        };

        const data = reactive({
            // 棋盘数据缓存
            boardData: [[]],
            // 棋盘样式
            boardStyle: {
                transform: '',
                width: 0,
                height: 0,
                margin: 0,
            },
            // 初始化
            init: false,
            // 判断是否有按键变化
            keyPerss: false,
            // 游戏是否结束
            isComplete: false,
            // 玩家位置
            playerLocation: [],
            // 箱子目的地缓存
            completeLocation: [],
            // 动画类型
            moveStatus: 'down',
            // 棋盘数据
            boardConfig: computed({
                get: () => {
                    return data.boardData;
                },
                set: (val) => {
                    var clientWidth = document.body.clientWidth;
                    data.boardData = JSON.parse(val[0].broad);
                    var boardWidth = data.boardData[0].length * 50;
                    var boardHeight = data.boardData.length * 50;
                    var scale = clientWidth / boardWidth
                    // 初始化棋盘样式
                    data.boardStyle.transform = 'scale(' + (scale > 1 ? 1 : scale) + ')';
                    data.boardStyle.width = boardWidth + 'px';
                    data.boardStyle.height = boardHeight + 'px';
                    data.boardStyle.margin = '-' + (boardHeight / 2) + 'px 0 0 -' + (boardWidth / 2) + 'px';
                    // 初始化玩家位置
                    for (let x = 0; x < data.boardData.length; x++) {
                        const item = data.boardData[x];
                        for (let y = 0; y < item.length; y++) {
                            const child = item[y];
                            if (child == 5) {
                                data.playerLocation = [x, y];
                            }
                        }
                    }
                    // 初始化箱子结束位置
                    data.completeLocation = [];
                    for (let x = 0; x < data.boardConfig.length; x++) {
                        const item = data.boardConfig[x];
                        for (let y = 0; y < item.length; y++) {
                            const child = item[y];
                            if (child == 4 || child == 6 || child == 7) {
                                data.completeLocation.push([x, y]);
                            }
                        }
                    }
                }
            }),
        });

        // 取消持续移动事件
        var clearTimer = () => {
            clearInterval(keyPerss.timer.up);
            clearInterval(keyPerss.timer.down);
            clearInterval(keyPerss.timer.left);
            clearInterval(keyPerss.timer.right);
        }
        // 获取箱子结束点位置，用于判断游戏结束
        // 获取玩家所在位置
        // 移动事件
        // 0 空位
        // 1 墙
        // 2 可移动的空地
        // 3 箱子
        // 4 箱子的目的地
        // 5 人物所在位置
        // 6 人物和箱子目的地重合
        // 7 箱子和目的地重合

        var keyBoardMove = (x, y) => {
            // 移动的方向上 下一个是空地 (移动)
            // 移动的方向上 下一个是墙 (跳过)
            // 移动的方向上 下一个是箱子 且 下一个的下一个是墙 或者箱子 (跳过)
            // 移动的方向上 下一个是箱子 (移动)
            // 下一个位置的 坐标
            var nextLocation = [data.playerLocation[0] + x, data.playerLocation[1] + y];
            // 下一个的下一个位置 的坐标
            var lastNextLocation = [data.playerLocation[0] + x + x, data.playerLocation[1] + y + y];
            // 下一个位置的值
            var nextBlockValue = data.boardConfig[nextLocation[0]][nextLocation[1]]
            // 玩家所在位置的值
            var playerLocationValue = data.boardConfig[data.playerLocation[0]][data.playerLocation[1]]
            // 下一个的下一个位置的值
            var lastNextLocationValue = data.boardConfig[lastNextLocation[0]] || data.boardConfig[lastNextLocation[0]] === 0 ? data.boardConfig[lastNextLocation[0]][lastNextLocation[1]] : null;

            if (nextBlockValue == 3 && lastNextLocationValue == 2) {
                // 下一个是箱子，而且下一个的下一个是空地
                if (playerLocationValue == 5) {
                    data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 2
                } else if (playerLocationValue == 6) {
                    data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 4
                }
                data.boardConfig[nextLocation[0]][nextLocation[1]] = 5
                data.boardConfig[lastNextLocation[0]][lastNextLocation[1]] = 3
                data.playerLocation = nextLocation;
            } if (nextBlockValue == 3 && lastNextLocationValue == 4) {
                // 把箱子推倒目标位置
                if (playerLocationValue == 5) {
                    data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 2
                } else if (playerLocationValue == 6) {
                    data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 4
                }
                data.boardConfig[nextLocation[0]][nextLocation[1]] = 5
                data.boardConfig[lastNextLocation[0]][lastNextLocation[1]] = 7
                data.playerLocation = nextLocation;
            } if (nextBlockValue == 7 && lastNextLocationValue == 2) {
                // 把箱子从目标位置退走
                data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 2
                data.boardConfig[nextLocation[0]][nextLocation[1]] = 6
                data.boardConfig[lastNextLocation[0]][lastNextLocation[1]] = 3
                data.playerLocation = nextLocation;
            } else if (nextBlockValue == 2 && playerLocationValue == 5) {
                data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 2
                data.boardConfig[nextLocation[0]][nextLocation[1]] = 5
                data.playerLocation = nextLocation;
                return
            } else if (nextBlockValue == 4 && playerLocationValue == 5) {
                // 下一个是箱子目的地
                data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 2
                data.boardConfig[nextLocation[0]][nextLocation[1]] = 6
                data.playerLocation = nextLocation;
                return
            } else if (nextBlockValue == 2 && playerLocationValue == 6) {
                // 从重合位置上离开
                data.boardConfig[data.playerLocation[0]][data.playerLocation[1]] = 4
                data.boardConfig[nextLocation[0]][nextLocation[1]] = 5;
                data.playerLocation = nextLocation;
            }
            checkComplete();
        };

        // 按下按键的事件
        var keyEvent = (key, x, y, type) => {
            if (!data.isComplete) {
                if (type == 'press' && !keyPerss.delay) {
                    keyPerss.delay = true;
                    clearTimer();
                    data.moveStatus = key
                    keyPerss.lastAnimationTimer = new window.Date().getTime();
                    keyBoardMove(x, y);
                    keyPerss.timer[key] = setInterval(() => {
                        keyPerss.lastAnimationTimer = new window.Date().getTime();
                        data.moveStatus = key
                        keyBoardMove(x, y)
                    }, 300);
                    setTimeout(() => {
                        keyPerss.delay = false;
                    }, 300);
                } else {
                    clearInterval(keyPerss.timer[key]);
                }
                nextTick(() => {
                    checkKeyPerss();
                });
            }
        }
        // 按键检查，没有在移动状态时，结束动画事件
        var checkKeyPerss = () => {
            var _keyPerss = keyBoradEvent.getKeyPerss(['up', 'down', 'left', 'right']);
            if (_keyPerss) {
                data.keyPerss = _keyPerss
            } else {
                var lastAniTime = new window.Date().getTime();
                if (keyPerss.clear) {
                    clearTimeout(keyPerss.clear);
                }
                keyPerss.clear = setTimeout(() => {
                    data.keyPerss = _keyPerss
                }, 300 - (lastAniTime - keyPerss.lastAnimationTimer));
            }
        };

        // 检查游戏是否结束
        var checkComplete = () => {
            if (data.isComplete) {
                return;
            }
            var isComplete = true;
            for (let i = 0; i < data.completeLocation.length; i++) {
                const item = data.completeLocation[i];
                var value = data.boardConfig[item[0]][item[1]];
                if (value != 7) {
                    isComplete = false;
                }
            }
            if (isComplete) {
                data.isComplete = isComplete;
                setTimeout(() => {
                    clearTimer();
                    alert('成功');
                }, 300);
            }
        };

        // 挂载时
        onMounted(async () => {
            data.boardConfig = await window.DB.level.where({
                id: parseInt(id.value)
            }).toArray();
            keyBoradEvent.on('up', () => keyEvent('up', -1, 0, 'press'), () => keyEvent('up', -1, 0, 'up'))
            keyBoradEvent.on('left', () => keyEvent('left', 0, -1, 'press'), () => keyEvent('left', 0, -1, 'up'))
            keyBoradEvent.on('down', () => keyEvent('down', 1, 0, 'press'), () => keyEvent('down', 1, 0, 'up'))
            keyBoradEvent.on('right', () => keyEvent('right', 0, 1, 'press'), () => keyEvent('right', 0, 1, 'up'))
            setTimeout(() => {
                data.init = true;
            }, 10);
        })
        // 注销
        onUnmounted(() => {
            keyBoradEvent.off('up');
            keyBoradEvent.off('down');
            keyBoradEvent.off('left');
            keyBoradEvent.off('right');
        });
        return {
            ...toRefs(data),
        }
    }
}
</script>

<style>
    .board { position: absolute;  left: 50%; top: 50%} 
    .row { height: 50px; }
    .NPC_board { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.2); }
    .block { width: 50px; height: 50px; float: left; position: relative; }
    .block_0 { background: #aaa;}
    /* .block_1 { background: #000; } */
    .block_2 { background: #fff; }
    .block_3 { background-color: #fff; background-image: url(../assets/block_3.png); }
    .block_4 { background: #fff; background-image: url(../assets/block_4.png); }
    .block_5 { background: #fff; background-image: url(../assets/block_5.png); }
    .block_6 { background: #fff; background-image: url(../assets/block_6.png); }
    .block_7 { background: #fff; background-image: url(../assets/block_7.png); }

    .npc { width: 50px; height: 50px;  animation-duration: 0.3s; position: absolute;  top: 0;left: 0;}
    .NPC_board .block { width : 50px; height : 50px; border: none; } 
    .NPC_board .block.transition {transition: all 0.3s linear;}
    .ani_up {animation-name: npc_top; background-image: url(/static/npc/t/t_1.png);}
    .ani_down {animation-name: npc_bottom; background-image: url(/static/npc/b/b_1.png);}
    .ani_left {animation-name: npc_left; background-image: url(/static/npc/l/l_1.png);}
    .ani_right {animation-name: npc_right; background-image: url(/static/npc/r/r_1.png); }
    .NPC_board .block.keyPerss {animation-iteration-count: infinite;}

    @keyframes npc_right {
        0% {background-image: url(/static/npc/r/r_1.png); }
        25% {background-image: url(/static/npc/r/r_2.png); }
        50% {background-image: url(/static/npc/r/r_1.png); }
        75% {background-image: url(/static/npc/r/r_3.png); }
        100% {background-image: url(/static/npc/r/r_1.png); }
    }
    @keyframes npc_left {
        0% {background-image: url(/static/npc/l/l_1.png); }
        25% {background-image: url(/static/npc/l/l_2.png); }
        50% {background-image: url(/static/npc/l/l_1.png); }
        75% {background-image: url(/static/npc/l/l_3.png); }
        100% {background-image: url(/static/npc/l/l_1.png); }
    }
    @keyframes npc_bottom {
        0% {background-image: url(/static/npc/b/b_1.png); }
        25% {background-image: url(/static/npc/b/b_2.png); }
        50% {background-image: url(/static/npc/b/b_1.png); }
        75% {background-image: url(/static/npc/b/b_3.png); }
        100% {background-image: url(/static/npc/b/b_1.png); }
    }
    @keyframes npc_top {
        0% {background-image: url(/static/npc/t/t_1.png); }
        25% {background-image: url(/static/npc/t/t_2.png); }
        50% {background-image: url(/static/npc/t/t_1.png); }
        75% {background-image: url(/static/npc/t/t_3.png); }
        100% {background-image: url(/static/npc/t/t_1.png); }
    }


</style>
